package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {
    //Alt enter implements 建立新的实现类的函数

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {

        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        // 对前端传来的明文密码进行md5加密，然后再进行比对
        // md5只能将密码转换成字符码，不能转换回去，所以进行对比的是md5码
        // 数据库数据更新之后，还要再查询一下IDE这边才能察觉到数据变化

        password=DigestUtils.md5DigestAsHex(password.getBytes());

        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            //当账号处于禁用状态时，无法登录
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    /**
     * 新增员工
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {

        System.out.println("当前线程的id:"+Thread.currentThread().getId());

        Employee employee = new Employee();

        //对象属性拷贝
        BeanUtils.copyProperties(employeeDTO,employee);

        //补充缺少的属性
        employee.setStatus(StatusConstant.ENABLE);
        //employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
        //employee.setCreateTime(LocalDateTime.now());
        //employee.setUpdateTime(LocalDateTime.now());

        //从线程局部变量区取出来当前用户ID
        //employee.setCreateUser(BaseContext.getCurrentId());
        //employee.setUpdateUser(BaseContext.getCurrentId());
        //创建人和修改人都是admin

        employeeMapper.insert(employee);

    }

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    //  /** enter 产生函数注释
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //Alt enter 顶端类 implements 建立新的实现类的函数

        //select * from employee limit 0,10
        //调整limit的参数，实现分页
        //mybites提供了pagehelper实现分页的逻辑,需要在pom.xml文件中引入
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

        //pagehelper返回的Page<Employee>不是要求的格式，要重新构造
        long total = page.getTotal();//返回数据行数量
        List<Employee> records = page.getResult();

        return new PageResult(total,records);

        //Employee是实体，用于存放我们的实体类，与数据库中的属性值基本保持一致，实现set和get的方法
        //对应数据库属性

        //controller层,web 层,用途： 控制层，负责具体模块的业务流程控制，需要调用service逻辑设计层的接口来控制业务流程。
        //controller通过接收前端H5或者App传过来的参数进行业务操作，再将处理结果返回到前端
        //功能函数，定义输入输出

        //service层，给controller层的类提供接口进行调用。一般就是自己写的方法封装起来，就是声明一下，具体实现在serviceImpl中。
        //分两层，一层声明，一层实现
        //实现函数功能

        //mapper层,别名： dao层,对数据库进行数据持久化操作，他的方法语句是直接针对数据库操作的，主要实现一些增删改查操作
        //操作数据库
    }

    /**
     * 更新员工数据信息
     * @param status
     * @param id
     */
    public void StartOrStop(Integer status, Long id) {
        //最终希望执行的操作: 单表修改
        //update employee set status =x where id= y
        Employee employee = new Employee();//创建一个雇员实体对象，将传入的属性打包
        employee.setStatus(status);
        employee.setId(id);
        employeeMapper.update(employee);//update操作本身可以复用，但这个StartOrStop不需要复用
    }


    /**
     * 查询员工信息
     * @param id
     * @return
     */
    public Employee GetById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("****");//将传给前端的密码加密
        return employee;
    }//在有返回的实现类里，默认会返回null，而且还不会报错，这其实就是因为返回的本质上是指针

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    public void update(EmployeeDTO employeeDTO) {

        //类型不同，传入的是EmployeeDTO，update函数需要的是Employee
        //使用对象属性拷贝
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO,employee);//使用对象属性拷贝

        //employee.setUpdateTime(LocalDateTime.now());//修改时间
        //employee.setUpdateUser(BaseContext.getCurrentId());//使用ThreadLocal(si ruai de)线程局部变量，提取保存的修改人Id

        employeeMapper.update(employee);
    }
}
